/*
 * Copyright 2020-2025 the original author or authors.
 * You cannot use this file unless authorized by the author.
 */

package org.ipig.commons.helper;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.ipig.commons.exception.UnsupportException;
import org.ipig.constants.DateTimeCnst;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期、时间、日期时间通用工具类<br>
 * <ul>
 * <li>鼓励使用,有线程安全保障
 * </ul>
 *
 * @author <a href="mailto:comchnts@163.com">chinats</a>
 * @version $Id: DateTimeHelper.java 22 2020-05-20 03:47:46Z ts <comchnts@163.com> $
 * @since 1.0
 */
public class DateTimeHelper {
    //日期时间特殊字符
    protected static final char[] DATE_TIME_SPECIAL_CHARACTER = {'-', ':', ' ', '.', 'T', '+'};

    /**
     * 将输入的 inDateTime日期字符格式化成14位长度的日期字符
     * <ul>支持多种形式的日期时间类型
     * <li>如20070817形式</li>
     * <li>如2007-08-17 16:49:17形式</li>
     * <li>如2019-07-17T17:25:58+08:00形式</li>
     * <li>如2018-10-29T09:48:10.766000形式</li>
     * <li>如2018-05-09 10:24:47.961480形式</li>
     * <br>注：
     * <li>1、内部会对格式后的日期时间字符会进行验证，如果验证失败会返回空字符串</li>
     * <li>2、如果inDateTime字符长度小于14长度，将用0补齐</li>
     * <li>3、如果inDateTime字符长度大于14长度，将进行截取</li>
     * <ul/>
     *
     * @param inDateTime 输入的日期时间
     * @return String
     */
    public static String formatDateTime(String inDateTime) {
        return formatDateTime(inDateTime, 14);
    }

    /**
     * 将输入的 inDateTime日期字符格式化成fixedLength长度的日期字符
     * <ul>支持多种形式的日期时间类型
     * <li>如20070817形式</li>
     * <li>如2007-08-17 16:49:17形式</li>
     * <li>如2019-07-17T17:25:58+08:00形式</li>
     * <li>如2018-10-29T09:48:10.766000形式</li>
     * <li>如2018-05-09 10:24:47.961480形式</li>
     * <br>注：
     * <li>1、内部会对格式后的日期时间字符会进行验证，如果验证失败会返回空字符串</li>
     * <li>2、如果inDateTime字符长度小于fixedLength长度，将用0补齐</li>
     * <li>3、如果inDateTime字符长度大于fixedLength长度，将进行截取</li>
     * <ul/>
     *
     * @param inDateTime  输入的日期时间
     * @param fixedLength 保留的固定长度
     * @return String
     */
    public static String formatDateTime(String inDateTime, int fixedLength) {
        String dateTime = StringUtils.EMPTY;
        if (!StringUtils.isBlank(inDateTime)) {
            inDateTime = DateTimeHelper.parseDateTimeToDigit(inDateTime);
            int length = StringUtils.length(inDateTime);
            if (length < fixedLength) {
                inDateTime = StringUtils.rightPad(inDateTime, fixedLength, "0");
            } else if (length > fixedLength) {
                inDateTime = StringUtils.substring(inDateTime, 0, fixedLength);
            }
            try {
                DateTimeHelper.parseDate(inDateTime);
                dateTime = inDateTime;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return dateTime;
    }


    /**
     * 两时间差转成Millisecond
     *
     * @param maxlocalDateTime LocalDateTime
     * @param minlocalDateTime LocalDateTime
     * @return Millisecond
     */
    public static long timeDifferenceToMillisecond(LocalDateTime maxlocalDateTime, LocalDateTime minlocalDateTime) {
        long range = 0;
        if (maxlocalDateTime != null && minlocalDateTime != null) {
            ZoneId zone = ZoneId.systemDefault();
            java.util.Date maxDate = Date.from(maxlocalDateTime.atZone(zone).toInstant());
            java.util.Date minDate = Date.from(minlocalDateTime.atZone(zone).toInstant());
            range = maxDate.getTime() - minDate.getTime();
        }
        return range;
    }


    /**
     * 将毫秒时间转化成Date
     *
     * @param milliseconds
     * @return
     */
    public static Date parseMsToDate(long milliseconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(milliseconds);
        calendar.get(Calendar.MILLISECOND);
        return calendar.getTime();
    }

    /**
     * 将时间字符串去格式转成long
     * "2007-08-17 16:49:17"----->20070817164917
     * "2019-07-17T17:25:58+08:00"----->201907171725580800
     * "2018-10-29T09:48:10.766000"----->20181029094810766000
     * "2018-05-09 10:24:47.961480"----->20180509102447961480
     *
     * @param dateValue
     * @return String
     */
    public static String parseDateTimeToDigit(String dateValue) {
        if (StringUtils.isBlank(dateValue)) {
            return dateValue;
        }
        StringBuilder sb = new StringBuilder();
        for (char c : dateValue.toCharArray()) {
            boolean deleted = false;
            for (char d : DATE_TIME_SPECIAL_CHARACTER) {
                //如果当前字符匹配上删除字符集和中的字符,则设置deleted标记后退出循环
                if (d == c) {
                    deleted = true;
                    break;
                }
            }
            if (!deleted) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 按照模式解析Date，最终转成Date类型的时间
     *
     * @param date    日期
     * @param pattern 模型
     * @return
     * @throws ParseException
     */
    public static Date parseDateToDate(Date date, DateTimeCnst.Pattern pattern) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern.pattern);
        String dateSdf = sdf.format(date);
        return DateUtils.parseDate(dateSdf, new String[]{pattern.pattern});
    }

    /**
     * 按照模式解析Date，最终转成Long类型的毫秒时间
     *
     * @param date    日期
     * @param pattern 模型
     * @return
     * @throws ParseException
     */
    public static Long parseDateToMs(Date date, DateTimeCnst.Pattern pattern) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern.pattern);
        String dateSdf = sdf.format(date);
        Long time = DateUtils.parseDate(dateSdf, new String[]{pattern.pattern}).getTime();
        return time;
    }

    /**
     * 解析日期时间
     *
     * @param isoDateTime  输入的日期时间数据
     * @param inFormatter  输入的格式
     * @param outFormatter 输出格式
     * @return
     */
    public static String parseDateTime(String isoDateTime, DateTimeCnst.Formatter inFormatter, DateTimeCnst.Formatter outFormatter) {
        String dateTime = "";
        try {
            LocalDateTime localDateTime = LocalDateTime.parse(isoDateTime, inFormatter.getCode());
            dateTime = localDateTime.format(outFormatter.getCode());
        } catch (Exception ex) {
            ex.printStackTrace();
            dateTime = getDateTime();
        }
        return dateTime;
    }

    /**
     * parseDateTime
     *
     * @param dateTime LocalDateTime
     * @param pattern  DateTimeCnst.Pattern
     * @return String
     */
    public static String parseDateTime(LocalDateTime dateTime, DateTimeCnst.Pattern pattern) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(pattern.pattern);
        return dateTime.format(dateTimeFormatter);
    }

    /**
     * 将yyyyMMddHHmmss 格式的字符串日期转化为java.time.LocalDateTime
     *
     * @param yyyyMMddHHmmss 必须为yyyyMMddHHmmss格式
     * @return java.time.LocalDateTime
     */
    public static java.time.LocalDateTime parseDateTime(String yyyyMMddHHmmss) {
        DateTimeFormatter format = DateTimeFormatter
                .ofPattern(DateTimeCnst.DATE_TIME);
        LocalDateTime dateTime = LocalDateTime.parse(yyyyMMddHHmmss, format);
        return dateTime;
    }

    /**
     * 将yyyyMMddHHmmss 格式的字符串日期转化为java.util.Date
     * <li>可能有未知异常</>
     *
     * @param yyyyMMddHHmmss 格式的字符串日期
     * @return java.util.Date
     */
    public static java.util.Date parseDate(final String yyyyMMddHHmmss) {
        DateTimeFormatter format = DateTimeFormatter
                .ofPattern(DateTimeCnst.DATE_TIME);
        LocalDateTime lastLocalDateTime = LocalDateTime.parse(yyyyMMddHHmmss,
                format);
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = lastLocalDateTime.atZone(zone).toInstant();
        java.util.Date date = Date.from(instant);
        return date;
    }


    /**
     * 将java.util.Date解析成字符类型为yyyyMMddHHmmss格式的日期时间
     *
     * @param date java.util.Date
     * @return yyyyMMddHHmmss格式的日期时间
     */
    public static String yyyyMMddHHmmss(final java.util.Date date) {
        LocalDateTime localDateTime = toLocalDateTime(date);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DateTimeCnst.DATE_TIME);
        return localDateTime.format(dateTimeFormatter);
    }

    /**
     * 将java.util.Date日期转化为java.time.LocalDateTime
     *
     * @param date java.util.Date日期
     * @return java.time.LocalDateTime
     */
    public static java.time.LocalDateTime toLocalDateTime(final java.util.Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime;
    }

    /**
     * 将java.util.Date日期转化为java.time.LocalDate
     *
     * @param date java.util.Date日期
     * @return java.time.LocalDate
     */
    public static java.time.LocalDate toLocalDate(final java.util.Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        LocalDate localDate = localDateTime.toLocalDate();
        return localDate;
    }

    /**
     * 将java.util.Date日期转化为java.time.LocalTime
     *
     * @param date java.util.Date日期
     * @return java.time.LocalTime
     */
    public static java.time.LocalTime toLocalTime(final java.util.Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        LocalTime localTime = localDateTime.toLocalTime();
        return localTime;
    }

    /**
     * 将LocalDateTime 转成  java.util.Date
     *
     * @param localDateTime java.time.LocalDateTime
     * @return java.util.Date
     */
    public static java.util.Date toDate(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取当前实时日期时间的简短数字,格式如下：
     * <ul>当前时间为20190522150407
     * <li>当为DateTimeCnst.Style.YEARS时：值如：2019</li>
     * <li>当为DateTimeCnst.Style.MONTHS时：值如：5</li>
     * <li>当为DateTimeCnst.Style.DAYS时：值如：22</li>
     * <li>当为DateTimeCnst.Style.HOURS时：值如：15</li>
     * <li>当为DateTimeCnst.Style.MINUTES时：值如：4</li>
     * <li>当为DateTimeCnst.Style.SECONDS时：值如：7</li>
     * <ul/>
     *
     * @param style 仅支持 YEARS、MONTHS、WEEKS、DAYS、HOURS、MINUTES、SECONDS
     * @return
     */
    public static int getShortDigitOfDateTime(java.util.Date date, DateTimeCnst.Style style) {
        LocalDateTime localDateTime = toLocalDateTime(date);
        return getShortDigitOfDateTime(localDateTime, style);
    }

    /**
     * 获取当前实时日期时间的简短数字,格式如下：
     * <ul>当前时间为20190522150407
     * <li>当为DateTimeCnst.Style.YEARS时：值如：2019</li>
     * <li>当为DateTimeCnst.Style.MONTHS时：值如：5</li>
     * <li>当为DateTimeCnst.Style.DAYS时：值如：22</li>
     * <li>当为DateTimeCnst.Style.HOURS时：值如：15</li>
     * <li>当为DateTimeCnst.Style.MINUTES时：值如：4</li>
     * <li>当为DateTimeCnst.Style.SECONDS时：值如：7</li>
     * <ul/>
     *
     * @param style 仅支持 YEARS、MONTHS、WEEKS、DAYS、HOURS、MINUTES、SECONDS
     * @return
     */
    public static int getShortDigitOfDateTime(DateTimeCnst.Style style) {
        LocalDateTime localDateTime = LocalDateTime.now();
        return getShortDigitOfDateTime(localDateTime, style);
    }

    /**
     * 获取当前实时日期时间的简短数字,格式如下：
     * <ul>当前时间为20190522150407
     * <li>当为DateTimeCnst.Style.YEARS时：值如：2019</li>
     * <li>当为DateTimeCnst.Style.MONTHS时：值如：5</li>
     * <li>当为DateTimeCnst.Style.DAYS时：值如：22</li>
     * <li>当为DateTimeCnst.Style.HOURS时：值如：15</li>
     * <li>当为DateTimeCnst.Style.MINUTES时：值如：4</li>
     * <li>当为DateTimeCnst.Style.SECONDS时：值如：7</li>
     * <ul/>
     *
     * @param style 仅支持 YEARS、MONTHS、WEEKS、DAYS、HOURS、MINUTES、SECONDS
     * @return
     */
    public static int getShortDigitOfDateTime(LocalDateTime localDateTime, DateTimeCnst.Style style) {
        int value = 0;
        switch (style) {
            case YEARS:
                value = localDateTime.getYear();
                break;
            case MONTHS:
                value = localDateTime.getMonthValue();
                break;
            case WEEKS:
                value = localDateTime.getDayOfWeek().getValue();
                break;
            case DAYS:
                value = localDateTime.getDayOfMonth();
                break;
            case HOURS:
                value = localDateTime.getHour();
                break;
            case MINUTES:
                value = localDateTime.getMinute();
                break;
            case SECONDS:
                value = localDateTime.getSecond();
                break;
            default:
        }
        return value;
    }

    /**
     * 获取单位为style数量为 plusNum之后的日期时间【yyyyMMddHHmmss】
     *
     * @param style   DateTimeCnst.Style
     * @param plusNum long
     * @return 格式为yyyyMMddHHmmss的日期时间字符串
     */
    public static String getDateTimePlus(DateTimeCnst.Style style,
                                         long plusNum) {
        LocalDateTime dateTime = LocalDateTime.now();
        return getDateTimePlus(dateTime, style, plusNum);
    }

    /**
     * 获取单位为style数量为 plusNum之后的日期时间【yyyyMMddHHmmss】
     *
     * @param localDateTime LocalDateTime
     * @param style         DateTimeCnst.Style
     * @param plusNum       long
     * @return 格式为yyyyMMddHHmmss的日期时间字符串
     */
    public static String getDateTimePlus(LocalDateTime localDateTime, DateTimeCnst.Style style,
                                         long plusNum) {
        if (localDateTime == null) {
            return StringUtils.EMPTY;
        }
        LocalDateTime dateTime = getLocalDateTimePlus(localDateTime, style, plusNum);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(DateTimeCnst.DATE_TIME);
        return dateTime.format(dateTimeFormatter);
    }

    /**
     * 获取单位为style数量为 plusNum之后的日期时间【LocalDateTime】
     *
     * @param style   DateTimeCnst.Style
     * @param plusNum long
     * @return LocalDateTime
     */
    public static LocalDateTime getLocalDateTimePlus(DateTimeCnst.Style style,
                                                     long plusNum) {
        LocalDateTime dateTime = LocalDateTime.now();
        return getLocalDateTimePlus(dateTime, style, plusNum);
    }

    /**
     * 获取单位为style数量为 plusNum之后的日期时间【LocalDateTime】
     *
     * @param localDateTime LocalDateTime
     * @param style         DateTimeCnst.Style
     * @param plusNum       long
     * @return LocalDateTime
     */
    public static LocalDateTime getLocalDateTimePlus(LocalDateTime localDateTime, DateTimeCnst.Style style,
                                                     long plusNum) {
        if (localDateTime == null) {
            return null;
        }
        if (DateTimeCnst.Style.YEARS == style) {
            localDateTime = localDateTime.plusYears(plusNum);
        } else if (DateTimeCnst.Style.MONTHS == style) {
            localDateTime = localDateTime.plusMonths(plusNum);
        } else if (DateTimeCnst.Style.WEEKS == style) {
            localDateTime = localDateTime.plusWeeks(plusNum);
        } else if (DateTimeCnst.Style.DAYS == style) {
            localDateTime = localDateTime.plusDays(plusNum);
        } else if (DateTimeCnst.Style.HOURS == style) {
            localDateTime = localDateTime.plusHours(plusNum);
        } else if (DateTimeCnst.Style.MINUTES == style) {
            localDateTime = localDateTime.plusMinutes(plusNum);
        } else if (DateTimeCnst.Style.SECONDS == style) {
            localDateTime = localDateTime.plusSeconds(plusNum);
        } else {
            throw new UnsupportException("Style=" + style.name());
        }
        return localDateTime;
    }

    /**
     * 获取单位为style数量为 plusNum之后的日期【yyyyMMdd】
     * <li>仅支持 DateTimeCnst.Style 为YEARS,MONTHS,WEEKS,DAYS;
     *
     * @param style   DateTimeCnst.Style
     * @param plusNum long
     * @return 格式为yyyyMMdd的日期字符串
     */
    public static String getDatePlus(DateTimeCnst.Style style,
                                     long plusNum) {
        LocalDate date = LocalDate.now();
        return getDatePlus(date, style, plusNum);
    }

    /**
     * 获取单位为style数量为 plusNum之后的日期【     * <li>日期模式【yyyyMMdd】】
     * <li>仅支持 DateTimeCnst.Style 为YEARS,MONTHS,WEEKS,DAYS;
     *
     * @param localDate LocalDate
     * @param style     DateTimeCnst.Style
     * @param plusNum   long
     * @return 格式为yyyyMMdd的日期字符串
     */
    public static String getDatePlus(LocalDate localDate, DateTimeCnst.Style style,
                                     long plusNum) {
        if (localDate == null) {
            return StringUtils.EMPTY;
        }
        LocalDate date = getLocalDatePlus(localDate, style, plusNum);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(DateTimeCnst.DATE);
        return date.format(dateTimeFormatter);
    }

    /**
     * 获取单位为style数量为 plusNum之后的日期【LocalDate】
     * <li>仅支持 DateTimeCnst.Style 为YEARS,MONTHS,WEEKS,DAYS;
     *
     * @param style   DateTimeCnst.Style
     * @param plusNum long
     * @return LocalDate
     */
    public static LocalDate getLocalDatePlus(DateTimeCnst.Style style,
                                             long plusNum) {
        LocalDate date = LocalDate.now();
        return getLocalDatePlus(date, style, plusNum);
    }

    /**
     * 获取单位为style数量为 plusNum之后的日期【LocalDate】
     * <li>仅支持 DateTimeCnst.Style 为YEARS,MONTHS,WEEKS,DAYS;
     *
     * @param date    LocalDate
     * @param style   DateTimeCnst.Style
     * @param plusNum long
     * @return
     */
    public static LocalDate getLocalDatePlus(LocalDate date, DateTimeCnst.Style style,
                                             long plusNum) {
        if (date == null) {
            return null;
        }
        if (DateTimeCnst.Style.YEARS == style) {
            date = date.plusYears(plusNum);
        } else if (DateTimeCnst.Style.MONTHS == style) {
            date = date.plusMonths(plusNum);
        } else if (DateTimeCnst.Style.WEEKS == style) {
            date = date.plusWeeks(plusNum);
        } else if (DateTimeCnst.Style.DAYS == style) {
            date = date.plusDays(plusNum);
        } else {
            throw new UnsupportException("Style=" + style.name());
        }
        return date;
    }

    /**
     * 获取单位为style数量为 minusNum之前的日期时间【yyyyMMddHHmmss】
     *
     * @param style    DateTimeCnst.Style
     * @param minusNum long
     * @return 格式为yyyyMMddHHmmss的日期时间字符串
     */
    public static String getDateTimeMinus(DateTimeCnst.Style style,
                                          long minusNum) {
        LocalDateTime localDateTime = LocalDateTime.now();
        return getDateTimeMinus(localDateTime, style, minusNum);
    }

    /**
     * 获取单位为style数量为 minusNum之前的日期时间【yyyyMMddHHmmss】
     *
     * @param localDateTime LocalDateTime
     * @param style         DateTimeCnst.Style
     * @param minusNum      long
     * @return 格式为yyyyMMddHHmmss的日期时间字符串
     */
    public static String getDateTimeMinus(LocalDateTime localDateTime, DateTimeCnst.Style style,
                                          long minusNum) {
        if (localDateTime == null) {
            return StringUtils.EMPTY;
        }
        LocalDateTime dateTime = getLocalDateTimeMinus(localDateTime, style, minusNum);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(DateTimeCnst.DATE_TIME);
        return dateTime.format(dateTimeFormatter);
    }

    /**
     * 获取单位为style数量为 minusNum之前的日期时间【LocalDateTime】
     *
     * @param minusNum long
     * @param style    DateTimeCnst.Style
     * @return
     */
    public static LocalDateTime getLocalDateTimeMinus(DateTimeCnst.Style style, long minusNum) {
        LocalDateTime dateTime = LocalDateTime.now();
        return getLocalDateTimeMinus(dateTime, style, minusNum);
    }

    /**
     * 获取单位为style数量为 minusNum之前的日期时间【LocalDateTime】
     *
     * @param localDateTime LocalDateTime
     * @param style         DateTimeCnst.Style
     * @param minusNum      long
     * @return LocalDateTime
     */
    public static LocalDateTime getLocalDateTimeMinus(LocalDateTime localDateTime, DateTimeCnst.Style style, long minusNum) {
        if (localDateTime == null) {
            return null;
        }
        if (DateTimeCnst.Style.YEARS == style) {
            localDateTime = localDateTime.minusYears(minusNum);
        } else if (DateTimeCnst.Style.MONTHS == style) {
            localDateTime = localDateTime.minusMonths(minusNum);
        } else if (DateTimeCnst.Style.WEEKS == style) {
            localDateTime = localDateTime.minusWeeks(minusNum);
        } else if (DateTimeCnst.Style.DAYS == style) {
            localDateTime = localDateTime.minusDays(minusNum);
        } else if (DateTimeCnst.Style.HOURS == style) {
            localDateTime = localDateTime.minusHours(minusNum);
        } else if (DateTimeCnst.Style.MINUTES == style) {
            localDateTime = localDateTime.minusMinutes(minusNum);
        } else if (DateTimeCnst.Style.SECONDS == style) {
            localDateTime = localDateTime.minusSeconds(minusNum);
        } else {
            throw new UnsupportException("Style=" + style.name());
        }
        return localDateTime;
    }

    /**
     * 获取单位为style数量为 minusNum之前的日期【yyyyMMdd】
     * <li>仅支持 DateTimeCnst.Style 为YEARS,MONTHS,WEEKS,DAYS;
     *
     * @param style    DateTimeCnst.Style
     * @param minusNum long
     * @return 格式为yyyyMMdd的日期字符串
     */
    public static String getDateMinus(DateTimeCnst.Style style,
                                      long minusNum) {
        LocalDate date = LocalDate.now();
        return getDateMinus(date, style, minusNum);
    }

    /**
     * 获取单位为style数量为 minusNum之前的日期【yyyyMMdd】
     * <li>仅支持 DateTimeCnst.Style 为YEARS,MONTHS,WEEKS,DAYS;
     *
     * @param localDate LocalDate
     * @param style     DateTimeCnst.Style
     * @param minusNum  long
     * @return 格式为yyyyMMdd的日期字符串
     */
    public static String getDateMinus(LocalDate localDate, DateTimeCnst.Style style,
                                      long minusNum) {
        if (localDate == null) {
            return StringUtils.EMPTY;
        }
        LocalDate date = getLocalDateMinus(localDate, style, minusNum);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(DateTimeCnst.DATE);
        return date.format(dateTimeFormatter);
    }

    /**
     * 获取单位为style数量为 minusNum之前的日期【LocalDate】
     * <li>仅支持 DateTimeCnst.Style 为YEARS,MONTHS,WEEKS,DAYS;
     *
     * @param minusNum long
     * @param style    DateTimeCnst.Style
     * @return LocalDate
     */
    public static LocalDate getLocalDateMinus(DateTimeCnst.Style style, long minusNum) {
        LocalDate date = LocalDate.now();
        return getLocalDateMinus(date, style, minusNum);
    }

    /**
     * 获取单位为style数量为 minusNum之前的日期【LocalDate】
     * <li>仅支持 DateTimeCnst.Style 为YEARS,MONTHS,WEEKS,DAYS;
     *
     * @param localDate LocalDate
     * @param style     DateTimeCnst.Style
     * @param minusNum  long
     * @return LocalDate
     */
    public static LocalDate getLocalDateMinus(LocalDate localDate, DateTimeCnst.Style style, long minusNum) {
        if (localDate == null) {
            return null;
        }
        if (DateTimeCnst.Style.YEARS == style) {
            localDate = localDate.minusYears(minusNum);
        } else if (DateTimeCnst.Style.MONTHS == style) {
            localDate = localDate.minusMonths(minusNum);
        } else if (DateTimeCnst.Style.WEEKS == style) {
            localDate = localDate.minusWeeks(minusNum);
        } else if (DateTimeCnst.Style.DAYS == style) {
            localDate = localDate.minusDays(minusNum);
        } else {
            throw new UnsupportException("Style=" + style.name());
        }
        return localDate;
    }

    /**
     * 日期时间模式【yyyyMMddHHmmss】
     *
     * @return String
     */
    public static String getDateTime() {
        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(DateTimeCnst.DATE_TIME);
        return localDateTime.format(dateTimeFormatter);
    }

    /**
     * 自定义日期时间模式
     *
     * @param formatter 日期时间模式
     * @return String
     */
    public static String getDateTime(final DateTimeCnst.Formatter formatter) {
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.format(formatter.getCode());
    }

    /**
     * 自定义日期时间模式
     *
     * @param dateTimePattern 日期时间模式
     * @return String
     */
    public static String getDateTime(final String dateTimePattern) {
        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(dateTimePattern);
        return localDateTime.format(dateTimeFormatter);
    }

    /**
     * 日期模式【yyyyMMdd】
     *
     * @return String
     */
    public static String getDate() {
        LocalDate localDate = LocalDate.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(DateTimeCnst.DATE);
        return localDate.format(dateTimeFormatter);
    }

    /**
     * 自定义日期模式
     *
     * @param datePattern 日期时间模式
     * @return String
     */
    public static String getDate(final String datePattern) {
        LocalDate localDate = LocalDate.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(datePattern);
        return localDate.format(dateTimeFormatter);
    }

    /**
     * 时间模式【HHmmss】
     *
     * @return String
     */
    public static String getTime() {
        LocalTime localTime = LocalTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(DateTimeCnst.TIME);
        return localTime.format(dateTimeFormatter);
    }

    /**
     * 自定义时间模式
     *
     * @param timePattern 日期时间模式
     * @return String
     */
    public static String getTime(final String timePattern) {
        LocalTime localTime = LocalTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(timePattern);
        return localTime.format(dateTimeFormatter);
    }
}